package com.example.jobback.service.recruiter.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.example.jobback.common.enums.RecruiterType;
import com.example.jobback.common.enums.VerifyCompanyRegisterStatus;
import com.example.jobback.config.AuthConfig;
import com.example.jobback.dto.RecruiterRegisterDto;
import com.example.jobback.mapper.CompanyMapper;
import com.example.jobback.mapper.RecruiterMapper;
import com.example.jobback.mapper.VerifyCompanyRecordMapper;
import com.example.jobback.po.*;
import com.example.jobback.req.common.password.ResetPasswordReq;
import com.example.jobback.req.common.phone.ResetPhoneReq;
import com.example.jobback.req.recruiter.company.register.RecruiterRegisterReq;
import com.example.jobback.resp.recruiter.auth.RecruiterLoginResp;
import com.example.jobback.resp.recruiter.auth.RecruiterRegisterCompanyResp;
import com.example.jobback.resp.recruiter.auth.VerifyCompanyRegisterStatusResp;
import com.example.jobback.result.Result;
import com.example.jobback.service.common.UserCommonService;
import com.example.jobback.service.recruiter.RecruiterAuthService;
import com.example.jobback.util.CACHEUtil;
import com.example.jobback.util.JWTUtil;
import com.example.jobback.util.SecureEncryptionUtil;
import com.example.jobback.util.TLUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.example.jobback.util.RedisConstants.*;
import static com.example.jobback.util.RedisConstants.RECRUITER_TTL;
import static java.time.LocalDateTime.now;

/**
 * @ClassName: RecruiterAuthServiceImpl
 * @Description:招聘者-身份核验服务实现类
 * @Author: lhb
 * @Date: 2025/6/21
 */
@Service
public class RecruiterAuthServiceImpl implements RecruiterAuthService {


    private final UserCommonService userCommonService;

    private final AuthConfig authConfig;

    private final CACHEUtil cacheUtil;

    private final Random random=new Random();

    private final CompanyMapper companyMapper;

    private final VerifyCompanyRecordMapper verifyCompanyRecordMapper;

    @Value("${recruiter.role}")
    private String defaultBossRole;

    private final RecruiterMapper recruiterMapper;

    public RecruiterAuthServiceImpl(AuthConfig authConfig, UserCommonService userCommonService, CACHEUtil cacheUtil, RecruiterMapper recruiterMapper, VerifyCompanyRecordMapper verifyCompanyRecordMapper, CompanyMapper companyMapper) {
        this.authConfig = authConfig;
        this.userCommonService = userCommonService;
        this.cacheUtil = cacheUtil;
        this.recruiterMapper = recruiterMapper;
        this.verifyCompanyRecordMapper = verifyCompanyRecordMapper;
        this.companyMapper = companyMapper;
    }

    /**
     * @Description: 登录
     * @param phone
     * @param code
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 10:36
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> LoginByPhone(String phone, String code) {
        //验证码验证
        String phoneAes=null;
        try {
            if(!userCommonService.verifyCode(phone,code)) throw new IllegalArgumentException("VALIDATION_ERROR:验证码错误");
            //加密手机号码
            phoneAes= SecureEncryptionUtil.encrypt(phone,authConfig.getPhoneSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 获取当前时间的小时部分,时间戳加随机数作为key，phoneAes作为value存入redis
        //key作为临时token的sub
        LocalDateTime now = now();
        String hourPart = now.format(DateTimeFormatter.ofPattern("MMddHH"));
        String key=RECRUITER_REGISTER_PHONE_KEY+hourPart+code;
        cacheUtil.set(key,phoneAes,RECRUITER_REGISTER_PHONE_TTL, TimeUnit.HOURS);
        String temporaryToken = JWTUtil.generateToken(hourPart+code,authConfig.getJwtTemporaryTime(),authConfig.getJwtTemporarySecret());
        //查找该电话号码的三端记录
        User user=userCommonService.getUserByPhoneAes(phoneAes);
        RecruiterLoginResp resp=new RecruiterLoginResp();
        if(user==null){
            //用户三端都未注册过
            resp.setStatus(false);
            resp.setToken(temporaryToken);
            return Result.success(resp);
        }
        Long userId = user.getUserId();
        Recruiter recruiter=recruiterMapper.getRecruiterByUserId(userId);
        if(recruiter == null) {
            //招聘端未注册
            resp.setStatus(false);
            resp.setToken(temporaryToken);
            return Result.success(resp);
        }else {
            BeanUtils.copyProperties(user, recruiter);
        }
        //删除三端登录记录，只允许一端登录
        userCommonService.deleteAllLoginKeys(userId);
        //获取token，写入redis
        String token = userCommonService.setRedisUser(recruiter,recruiter.getUserId(),RECRUITER_KEY,authConfig.getJwtRecruiterSecret(),RECRUITER_TTL,TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        //登录成功删除存储电话号码的key
        cacheUtil.deleteKeySafely(key);
        resp.setToken(token);
        resp.setStatus(true);
        return Result.success(resp);
    }

    /**
     * @Description: 注册
     * @param req
     * @param token
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 10:39
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> applyRegisterCompany(RecruiterRegisterReq req, String token) {
        if(token==null) throw new IllegalArgumentException("CLIENT_ERROR：token缺失");
        String suffix=JWTUtil.checkToken(token,authConfig.getJwtTemporarySecret());
        if (StrUtil.isBlank(suffix)) throw new IllegalArgumentException("VALIDATION_ERROR:临时token认证失败");
        String key=RECRUITER_REGISTER_PHONE_KEY+suffix;
        String phoneAes=cacheUtil.get(key);
        if(phoneAes==null) throw new IllegalArgumentException("VALIDATION_ERROR:临时token过期，请重新登录");
        //检测用户是否需要注册
        if(validatedIsRecruiter(phoneAes)) throw new RuntimeException("该用户已绑定不可注册");
        RecruiterRegisterDto recruiterRegisterDto=new RecruiterRegisterDto();
        BeanUtils.copyProperties(req, recruiterRegisterDto);
        recruiterRegisterDto.setPhoneAes(phoneAes);
        recruiterRegisterDto.setType(RecruiterType.BOSS);
        String recruiterJson= JSON.toJSONString(recruiterRegisterDto);
        //存入mysql中的审核表，后续跨服务处理
        VerifyCompanyRecord record=verifyCompanyRecordMapper.getRecordByPhoneAes(phoneAes);
        if(record==null) {
            //首次注册
            if(verifyCompanyRecordMapper.addRecord(phoneAes, VerifyCompanyRegisterStatus.VERIFY_REVIEW)==0){
                throw new RuntimeException("注册信息提交失败");
            }
        }else {
            //审核失败再提交
            if(record.getStatus().equals(VerifyCompanyRegisterStatus.VERIFY_FAILED)){
                if(verifyCompanyRecordMapper.updateRecord(phoneAes,VerifyCompanyRegisterStatus.VERIFY_REVIEW,"")==0){
                    throw new RuntimeException("注册信息提交失败");
                }
            }
        }
        //用sortSet的结构存入redis
        cacheUtil.setZSet(VERIFY_RECRUITER_REGISTER_USERS_KEY,phoneAes,System.currentTimeMillis());
        cacheUtil.setNoTtl(VERIFY_RECRUITER_REGISTER_USER_KEY+phoneAes,recruiterJson);
        return Result.success();
    }

    /**
     * @Description: 获取审核状态，用于招聘者注册
     * @param token
     * @return Result<VerifyCompanyRegisterStatusResp>
     * @Author lhb
     * @CreateTime 2025/6/21 10:43
     */
    @Override
    public Result<VerifyCompanyRegisterStatusResp> getVerifyMessage(String token) {
        VerifyCompanyRegisterStatusResp resp=new VerifyCompanyRegisterStatusResp();
        resp.setCompanyResp(new RecruiterRegisterCompanyResp());
        if(token==null) {
            throw new IllegalArgumentException("CLIENT_ERROR：token缺失");
        }
        String suffix=JWTUtil.checkToken(token,authConfig.getJwtTemporarySecret());
        if (StrUtil.isBlank(suffix)) {
            throw new IllegalArgumentException("VALIDATION_ERROR:临时token认证失败");
        }
        String key=RECRUITER_REGISTER_PHONE_KEY+suffix;
        String phoneAes=cacheUtil.get(key);
        if(phoneAes==null) {
            throw new IllegalArgumentException("VALIDATION_ERROR:临时token过期，请重新登录");
        }
        //检测用户是否需要注册
        if(validatedIsRecruiter(phoneAes)) {
            throw new RuntimeException("该用户已绑定不可注册");
        }
        VerifyCompanyRecord record = verifyCompanyRecordMapper.getRecordByPhoneAes(phoneAes);
        //当没有注册过时，返回user表的姓名
        if(record==null){
            resp.setStatus(VerifyCompanyRegisterStatus.NOT_SUBMITTED);
            User user = userCommonService.getUserByPhoneAes(phoneAes);
            if(user==null) return Result.success(resp);
            //没有提交默认user表的姓名
            resp.getCompanyResp().setUserName(user.getName());
            return Result.success(resp);
        }
        resp.setStatus(record.getStatus());
        resp.setFailedMessage(record.getFailedMessage());
        User user = userCommonService.getUserByPhoneAes(phoneAes);
        if(user==null) return Result.success(resp);
        //获取公司信息
        String companyMessageJson = cacheUtil.get(VERIFY_RECRUITER_REGISTER_USER_KEY + phoneAes);
        if(companyMessageJson!=null) {
            RecruiterRegisterDto recruiterRegisterDto = JSON.parseObject(companyMessageJson, RecruiterRegisterDto.class);
            BeanUtils.copyProperties(recruiterRegisterDto,resp.getCompanyResp());
        }else {
            //这一步不太可能执行
            resp.getCompanyResp().setUserName(user.getName());
        }
        return Result.success(resp);
    }

    /**
     * @Description: 跨服务-注册公司
     * @param recruiterRegisterDto
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 10:48
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> registerCompany(RecruiterRegisterDto recruiterRegisterDto) {
        Company company=new Company();
        BeanUtils.copyProperties(recruiterRegisterDto, company);
        if(companyMapper.registerCompany(company)==0) throw new RuntimeException("注册失败");
        Recruiter recruiter=new Recruiter();
        recruiter.setUserId(recruiterRegisterDto.getUserId());
        recruiter.setCompanyId(company.getCompanyId());
        recruiter.setType(recruiterRegisterDto.getType());
        recruiter.setRole(defaultBossRole);
        if(recruiterMapper.register(recruiter)==0) throw new RuntimeException("注册失败");
        return Result.success();
    }

    /**
     * @Description: 退出登录
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 10:49
     */
    @Override
    public Result<Object> LoginOut() {
        Long userId= TLUtil.get(TLUtil.R).getUserId();
        String key=RECRUITER_KEY+userId.toString();
        if (cacheUtil.deleteIfExists(key))return Result.success();
        throw new RuntimeException("登出失败");
    }

    /**
     * @Description: 新招聘者登录
     * @param phone
     * @param password
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/23 15:04
     */
    @Override
    public Result<RecruiterLoginResp> login(String phone, String password) {
        String phoneAes= "";
        String passwordAes="";
        //加密电话号码和密码
        try {
            phoneAes = SecureEncryptionUtil.encrypt(phone,authConfig.getPhoneSecret());
            passwordAes = SecureEncryptionUtil.encrypt(password,authConfig.getPasswordSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //查看用户记录
        User user=userCommonService.getUserByPhoneAes(phoneAes);
        if(user==null) throw new NullPointerException("无用户记录");
        Long userId = user.getUserId();
        //核验密码
        if(!userCommonService.authUserPassword(userId,passwordAes)){
            throw new IllegalArgumentException("VALIDATION_ERROR:用户名或者密码错误");
        }
        RecruiterLoginResp resp=new RecruiterLoginResp();
        //查看招聘者端
        Recruiter recruiter=recruiterMapper.getRecruiterByUserId(userId);
        if(recruiter == null) {
            //招聘端未注册
            // 获取当前时间的小时部分,时间戳加随机数作为key，phoneAes作为value存入redis
            //key作为临时token的sub
            String code = String.format("%04d", random.nextInt(10000));
            LocalDateTime now = now();
            String hourPart = now.format(DateTimeFormatter.ofPattern("MMddHH"));
            String key=RECRUITER_REGISTER_PHONE_KEY+hourPart+code;
            cacheUtil.set(key,phoneAes,RECRUITER_REGISTER_PHONE_TTL, TimeUnit.HOURS);
            String temporaryToken = JWTUtil.generateToken(hourPart+code,authConfig.getJwtTemporaryTime(),authConfig.getJwtTemporarySecret());
            //构造响应体
            resp.setStatus(false);
            resp.setToken(temporaryToken);
            return Result.success(resp);
        }else {
            BeanUtils.copyProperties(user, recruiter);
        }
        //删除三端登录记录，只允许一端登录
        userCommonService.deleteAllLoginKeys(userId);
        //获取token，写入redis
        String token = userCommonService.setRedisUser(recruiter,recruiter.getUserId(),RECRUITER_KEY,authConfig.getJwtRecruiterSecret(),RECRUITER_TTL,TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        resp.setToken(token);
        resp.setStatus(true);
        return Result.success(resp);
    }

    /**
     * @Description: 用户个人注册
     * @param phone
     * @param password
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/23 15:24
     */
    @Override
    public Result<Object> register(String phone, String password) {
        String phoneAes= null;
        String passwordAes=null;
        //加密电话号码和密码
        try {
            phoneAes = SecureEncryptionUtil.encrypt(phone,authConfig.getPhoneSecret());
            passwordAes = SecureEncryptionUtil.encrypt(password,authConfig.getPasswordSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //查看用户记录
        if(userCommonService.getUserByPhoneAes(phoneAes)!=null) {
            throw new IllegalArgumentException("VALIDATION_ERROR:该电话号码已被注册");
        }
        User user= userCommonService.registerUser(phoneAes);
        Long userId=user.getUserId();
        if(userCommonService.registerUserAuth(userId,passwordAes)==0) {
            throw new RuntimeException("注册失败");
        }
        return Result.success("注册成功");
    }

    /**
     * @Description: 修改密码
     * @param resetPasswordReq
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/7/25 17:24
     */
    @Override
    public Result<Object> resetPassword(ResetPasswordReq resetPasswordReq) {
        Recruiter recruiter = TLUtil.get(TLUtil.R);
        Long userId = recruiter.getUserId();
        String phoneAes = recruiter.getPhoneAes();
        return userCommonService.resetPassword(resetPasswordReq, phoneAes, userId);
    }

    /**
     * @Description: 更换手机号
     * @param resetPhoneReq
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/7/26 14:03
     */
    @Override
    public Result<Object> resetPhone(ResetPhoneReq resetPhoneReq) {
        Recruiter recruiter = TLUtil.get(TLUtil.R);
        Long userId = recruiter.getUserId();
        String phoneAes = recruiter.getPhoneAes();
        return userCommonService.resetPhone(resetPhoneReq, phoneAes, userId);
    }

    /**
     * @Description: 验证是否是招聘者
     * @param phoneAes
     * @return boolean
     * @Author lhb
     * @CreateTime 2025/6/21 10:42
     */
    private boolean validatedIsRecruiter(String phoneAes) {
        boolean result = false;
        User user = userCommonService.getUserByPhoneAes(phoneAes);
        if(user != null) {
            Recruiter recruiter = recruiterMapper.getRecruiterByUserId(user.getUserId());
            result = recruiter != null;
        }
        return result;
    }


}
